Course schedule [Topological Sort]¶
Time: O(|V|+|E|); Space: O(|E|); medium
There are a total of numCourses courses you have to take, labeled from 0 to numCourses - 1. Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0, 1] Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Example 1:
Input: numCourses = 2, prerequisites = [[1,0]]
Output: True
Explanation:
There are a total of 2 courses to take.
To take course 1 you should have finished course 0.
So it is possible.
Example 2:
Input: numCourses = 2, prerequisites = [[1,0], [0,1]]
Output: False
Explanation:
There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1.
So it is impossible.
Hints:
This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses. There are several ways to represent a graph. For example, the input prerequisites is a graph represented by a list of edges. Is this graph representation appropriate?
Topological Sort via DFS - A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
Topological sort could also be done via BFS.
[1]:
from collections import deque
class Solution1(object):
def canFinish(self, numCourses, prerequisites):
"""
:type numCourses: int
:type prerequisites: List[List[int]]
:rtype: bool
"""
zero_in_degree_queue, in_degree, out_degree = deque(), {}, {}
for i, j in prerequisites:
if i not in in_degree:
in_degree[i] = set()
if j not in out_degree:
out_degree[j] = set()
in_degree[i].add(j)
out_degree[j].add(i)
for i in range(numCourses):
if i not in in_degree:
zero_in_degree_queue.append(i)
while zero_in_degree_queue:
prerequisite = zero_in_degree_queue.popleft()
if prerequisite in out_degree:
for course in out_degree[prerequisite]:
in_degree[course].discard(prerequisite)
if not in_degree[course]:
zero_in_degree_queue.append(course)
del out_degree[prerequisite]
if out_degree:
return False
return True
[3]:
s = Solution1()
numCourses = 2
prerequisites = [[1,0]]
assert s.canFinish(numCourses, prerequisites) == True
numCourses = 2
prerequisites = [[1,0], [0,1]]
assert s.canFinish(numCourses, prerequisites) == False